package controllers.administrator;

import java.util.Collection;
import java.util.Date;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import services.AdministratorService;
import services.EventService;
import services.RouteService;
import controllers.AbstractController;
import domain.Event;
import domain.Route;
import forms.RouteForm;

@Controller
@RequestMapping("/route/administrator")
public class RouteAdministratorController extends AbstractController {

	// Services

	@Autowired
	private RouteService routeService;
	@Autowired
	private EventService eventService;
	@Autowired
	private AdministratorService administratorService;

	// Constructors

	public RouteAdministratorController() {
		super();
	}

	// Listing
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView list(@RequestParam int eventId) {
		ModelAndView result;
		Collection<Route> routes;
		Date currentMoment = new Date();
		routes = routeService.findByEventId(eventId);
		Event evento = eventService.findOne(eventId);
		Boolean isOwner = evento.getAdministrator().equals(
				administratorService.findByPrincipal());
		Boolean notStarted = evento.getStartMoment().after(currentMoment);
		Boolean noParticipants = evento.getRegistrations().isEmpty();

		result = new ModelAndView("route/list");
		result.addObject("requestURI", "route/administrator/list.do");
		result.addObject("routes", routes);
		result.addObject("isOwner", isOwner);
		result.addObject("notStarted", notStarted);
		result.addObject("noParticipants", noParticipants);
		result.addObject("evento", evento);
		result.addObject("eventId", eventId);
		result.addObject("backURI", "/event/administrator/edit.do?eventId="+eventId);
		return result;
	}

	@RequestMapping(value = "/ordered/list", method = RequestMethod.GET)
	public ModelAndView orderedList() {
		ModelAndView result;

		Collection<Route> routes = routeService
				.findByAdministratorOrderedByRating(administratorService
						.findByPrincipal().getId());

		result = new ModelAndView("route/list");
		result.addObject("requestURI", "route/list.do");
		result.addObject("routes", routes);
		result.addObject("ordered", true);
		result.addObject("backURI", "/welcome/index.do");
		return result;
	}

	@RequestMapping(value = "/ownedRoutes", method = RequestMethod.GET)
	public ModelAndView ownedList() {
		ModelAndView result;
		Collection<Route> routes;
		routes = routeService.findRoutesByAdministrator();

		result = new ModelAndView("route/list");
		result.addObject("requestURI", "route/administrator/ownedRoutes.do");
		result.addObject("routes", routes);
		result.addObject("backURI", "/welcome/index.do");
		return result;
	}

	// Creation
	@RequestMapping(value = "/create", method = RequestMethod.GET)
	public ModelAndView create(@RequestParam int eventId) {
		ModelAndView result;
		Event event = eventService.findOne(eventId);
		
		RouteForm  routeForm = new RouteForm();
		routeForm.setEventId(eventId);
	
		Boolean isOwner = event.getAdministrator().equals(
				administratorService.findByPrincipal());
		Boolean isNew = true;

		result = new ModelAndView("route/edit");
		result.addObject("requestURI", "route/administrator/edit.do");
		result.addObject("isOwner", isOwner);
		result.addObject("isNew", isNew);
		result.addObject("routeForm", routeForm);
		result.addObject("eventId", eventId);
		result.addObject("backURI", "/route/administrator/list.do?eventId="+eventId);

		return result;

	}

	// Edition

	@RequestMapping(value = "/edit", method = RequestMethod.POST, params = "save")
	public ModelAndView save(@Valid RouteForm routeForm, BindingResult binding) {
		ModelAndView result;
		Route route = routeService.reconstruct(routeForm);
		int eventId = route.getEvent().getId();
		

		if (binding.hasErrors()) {
			result = createEditModelAndView(routeForm);
			
		} else {
			try {
				
				routeService.save(route);
				result = new ModelAndView("redirect:list.do?eventId="+eventId);
			} catch (Throwable oops) {
				result = createEditModelAndView(routeForm, "route.commit.error");
			}
		}
		result.addObject("backURI", "/route/administrator/list.do?eventId="+eventId);
		return result;

	}
	//View
	
	@RequestMapping(value = "/edit", method = RequestMethod.GET)
	public ModelAndView edit(@RequestParam int routeId) {
		ModelAndView result;
		
		Route route = routeService.findOne(routeId);
		int eventId = route.getEvent().getId();
		RouteForm routeForm = new RouteForm();
		
		routeForm.setDifficulty(route.getDifficulty());
		routeForm.setName(route.getName());
		routeForm.setRating(route.getRating());
		routeForm.setLength(route.getLength());
		routeForm.setEventId(route.getEvent().getId());
		
	
		Boolean isOwner = route.getAdministrator().equals(
				administratorService.findByPrincipal());
		Boolean isNew = false;

		result = new ModelAndView("route/edit");
		result.addObject("requestURI", "route/administrator/edit.do");
		result.addObject("isOwner", isOwner);
		result.addObject("isNew", isNew);
		result.addObject("routeForm", routeForm);
		result.addObject("backURI", "/route/administrator/list.do?eventId="+eventId);

		return result;

	}


	// Ancillary methods
	protected ModelAndView createEditModelAndView(RouteForm routeForm) {
		ModelAndView result;
		result = createEditModelAndView(routeForm, null);
		return result;

	}

	protected ModelAndView createEditModelAndView(RouteForm routeForm, String message) {
		ModelAndView result;

		result = new ModelAndView("route/edit");
		result.addObject("routeForm", routeForm);
		result.addObject("message", message);

		return result;

	}

}
